<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Animated Ball with Trails</title>
    <style>
        body {
            margin: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: white;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="800" height="400"></canvas>
    <script>
        // 获取Canvas元素和绘图上下文
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
        
        // 球体属性
        const ball = {
            x: 50,
            y: canvas.height / 2,
            radius: 10,
            speed: 2,
            trailPoints: [], // 存储轨迹点
            trailMaxLength: 50, // 轨迹最大长度
            lines: [], // 存储速度线
            lineCount: 10, // 速度线数量
            lineLength: 15, // 速度线长度
            square: {
                size: 15,
                rotation: 0,
                rotationSpeed: 0.05,
                show: false,
                launchedSquares: [], // 存储已抛出的小方块
                launchTimer: null, // 用于控制自动抛出的计时器
                launchInterval: 5000, // 自动抛出间隔（毫秒）
                texts: [ // 要显示的文本数组
                    "Hello, World!",
                    "This is an animation demo",
                    "Using Canvas in HTML5",
                    "Animated text boxes",
                    "Created with JavaScript",
                    "抛物线动画效果",
                    "文本框逐渐变大",
                    "然后向左移动消失",
                    "循环展示多段文本",
                    "最后一个示例文本"
                ],
                currentTextIndex: 0 // 当前显示的文本索引
            },
            hasStopped: false // 标记球体是否已停止移动
        };
        
        // 初始化速度线
        function initLines() {
            for (let i = 0; i < ball.lineCount; i++) {
                addLine();
            }
        }
        
        // 添加新的速度线
        function addLine() {
            ball.lines.push({
                x: ball.x - ball.radius - Math.random() * 100,
                y: ball.y + (Math.random() * 40 - 20),
                length: ball.lineLength * (0.7 + Math.random() * 0.6),
                speed: ball.speed * (1.5 + Math.random())
            });
        }
        
        // 绘制普通平面圆
        function drawBall() {
            ctx.beginPath();
            ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
            ctx.fillStyle = '#6495ED'; // 使用纯色填充
            ctx.fill();
            ctx.closePath();
            
            // 绘制球体左上角的旋转小方块
            if (ball.square.show) {
                drawSquare();
            }
            
            // 绘制所有被抛出的小方块或文本框
            ball.square.launchedSquares.forEach(launched => {
                drawLaunchedSquare(launched);
            });
        }
        
        // 绘制旋转的小方块
        function drawSquare() {
            ctx.save();
            ctx.translate(ball.x - ball.radius - ball.square.size, ball.y - ball.radius - ball.square.size);
            ctx.rotate(ball.square.rotation);
            
            // 创建线性渐变
            const squareGradient = ctx.createLinearGradient(
                -ball.square.size / 2, 
                -ball.square.size / 2, 
                ball.square.size / 2, 
                ball.square.size / 2
            );
            squareGradient.addColorStop(0, '#FF6B6B'); // 浅红色
            squareGradient.addColorStop(1, '#B83227'); // 深红色
            
            ctx.fillStyle = squareGradient;
            ctx.fillRect(-ball.square.size / 2, -ball.square.size / 2, ball.square.size, ball.square.size);
            
            // 绘制白色边框
            ctx.strokeStyle = 'white';
            ctx.lineWidth = 1;
            ctx.strokeRect(-ball.square.size / 2, -ball.square.size / 2, ball.square.size, ball.square.size);
            
            ctx.restore();
        }
        
        // 绘制被抛出的小方块或文本框
        function drawLaunchedSquare(launched) {
            const progress = Math.min(1, (Date.now() - launched.startTime) / launched.duration);
            
            if (progress < launched.expandDuration / launched.duration) {
                // 阶段1：抛物线运动并逐渐变大
                const expandProgress = progress * launched.duration / launched.expandDuration;
                
                // 计算抛物线轨迹
                const t = expandProgress * 100;
                //console.log('计算抛物线轨迹',progress,  launched.duration,launched.expandDuration,expandProgress,launched.launchDuration);
                const launchX = launched.startX - launched.launchSpeedX * t;
                const launchY = launched.startY + launched.launchSpeedY * t + 0.1 * 0.9 * t*t ;
                console.log(launched.startX,  launched.startY,launched.launchSpeedX,launched.launchSpeedY,t);
                console.log(launchX, launchY);
                // 计算当前大小（从小变大）
                const currentSize = launched.initialSize + (launched.targetSize - launched.initialSize) * expandProgress;
                
                ctx.save();
                ctx.translate(launchX, launchY);
                ctx.rotate(ball.square.rotation + expandProgress * Math.PI * 4); // 旋转
                
                // 创建线性渐变
                const squareGradient = ctx.createLinearGradient(
                    -currentSize / 2, 
                    -currentSize / 2, 
                    currentSize / 2, 
                    currentSize / 2
                );
                squareGradient.addColorStop(0, '#FF6B6B'); // 浅红色
                squareGradient.addColorStop(1, '#B83227'); // 深红色
                
                ctx.fillStyle = squareGradient;
                ctx.fillRect(-currentSize / 2, -currentSize / 2, currentSize, currentSize);
                
                // 绘制白色边框
                ctx.strokeStyle = 'white';
                ctx.lineWidth = 1;
                ctx.strokeRect(-currentSize / 2, -currentSize / 2, currentSize, currentSize);
                
                ctx.restore();
            } else if (progress < (launched.expandDuration + launched.staticDuration) / launched.duration) {
                // 阶段2：静止显示文本框
                const textBoxX = canvas.width / 2 - launched.targetSize / 2;
                const textBoxY = canvas.height / 2 - launched.targetHeight / 2;
                
                // 绘制文本框背景
                ctx.fillStyle = 'white';
                ctx.fillRect(textBoxX, textBoxY, launched.targetSize, launched.targetHeight);
                
                // 绘制文本框边框
                ctx.strokeStyle = '#1E3A8A';
                ctx.lineWidth = 2;
                ctx.strokeRect(textBoxX, textBoxY, launched.targetSize, launched.targetHeight);
                
                // 绘制文本
                ctx.fillStyle = '#333';
                ctx.font = '20px Arial';
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                ctx.fillText(launched.text, textBoxX + launched.targetSize / 2, textBoxY + launched.targetHeight / 2);
            } else {
                // 阶段3：向左移动并逐渐消失
                const moveProgress = (progress * launched.duration - launched.expandDuration - launched.staticDuration) / 
                                    (launched.duration - launched.expandDuration - launched.staticDuration);
                
                const textBoxX = canvas.width / 2 - launched.targetSize / 2 - moveProgress * canvas.width * 0.7;
                const textBoxY = canvas.height / 2 - launched.targetHeight / 2;
                
                // 计算当前大小（从大变小）
                const currentSize = launched.targetSize * (1 - moveProgress * 0.5);
                const currentHeight = launched.targetHeight * (1 - moveProgress * 0.5);
                
                // 绘制文本框背景
                ctx.fillStyle = 'rgba(255, 255, 255, ' + (1 - moveProgress) + ')';
                ctx.fillRect(textBoxX, textBoxY, currentSize, currentHeight);
                
                // 绘制文本框边框
                ctx.strokeStyle = 'rgba(30, 58, 138, ' + (1 - moveProgress) + ')';
                ctx.lineWidth = 2;
                ctx.strokeRect(textBoxX, textBoxY, currentSize, currentHeight);
                
                // 绘制文本
                ctx.fillStyle = 'rgba(51, 51, 51, ' + (1 - moveProgress) + ')';
                ctx.font = '20px Arial';
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                ctx.fillText(launched.text, textBoxX + currentSize / 2, textBoxY + currentHeight / 2);
            }
        }
        
        // 绘制轨迹
        function drawTrail() {
            if (ball.trailPoints.length < 2) return;
            
            ctx.beginPath();
            ctx.moveTo(ball.trailPoints[0].x, ball.trailPoints[0].y);
            
            for (let i = 1; i < ball.trailPoints.length; i++) {
                // 根据点的位置决定透明度，使轨迹有淡出效果
                const alpha = i / ball.trailPoints.length;
                ctx.strokeStyle = `rgba(100, 149, 237, ${alpha * 0.7})`;
                ctx.lineTo(ball.trailPoints[i].x, ball.trailPoints[i].y);
                ctx.stroke();
                ctx.beginPath();
                ctx.moveTo(ball.trailPoints[i].x, ball.trailPoints[i].y);
            }
            
            ctx.closePath();
        }
        
        // 绘制速度线
        function drawLines() {
            ball.lines.forEach(line => {
                ctx.beginPath();
                ctx.moveTo(line.x, line.y);
                ctx.lineTo(line.x + line.length, line.y);
                
                // 根据线的长度决定透明度，使短线更淡
                const alpha = line.length / ball.lineLength * 0.8;
                ctx.strokeStyle = `rgba(100, 149, 237, ${alpha})`;
                ctx.lineWidth = 1 + line.length / ball.lineLength;
                ctx.stroke();
                ctx.closePath();
            });
        }
        
        // 抛出一个新的小方块
        function launchNewSquare() {
            // 获取当前文本
            const text = ball.square.texts[ball.square.currentTextIndex];
            ball.square.currentTextIndex = (ball.square.currentTextIndex + 1) % ball.square.texts.length;
            
            // 计算旋转小方块的起始位置
            const squareStartX = ball.x - ball.radius - ball.square.size;
            const squareStartY = ball.y - ball.radius - ball.square.size;
            console.log(squareStartX, squareStartY);
            // 添加新的抛出对象
            ball.square.launchedSquares.push({
                text: text,
                initialSize: ball.square.size,
                targetSize: canvas.width * 0.3, // 宽度为画布的60%
                targetHeight: canvas.height * 0.2, // 高度为画布的50%
                startTime: Date.now(),
                duration: 4000, // 总持续时间（毫秒）
                expandDuration: 1500, // 变大阶段持续时间
                staticDuration: 2000, // 静止阶段持续时间
                launchSpeedX: 3,
                launchSpeedY: -8,
                startX: squareStartX,
                startY: squareStartY,
                gravity: 0.2
            });
            
            // 移除已完成动画的对象
            ball.square.launchedSquares = ball.square.launchedSquares.filter(launched => {
                return (Date.now() - launched.startTime) < launched.duration;
            });
        }
        
        // 更新动画
        function update() {
            // 清除画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            // 更新球体位置（未到达右边界时）
            if (ball.x < canvas.width - ball.radius) {
                ball.x += ball.speed;
                
                // 添加新的轨迹点
                ball.trailPoints.push({x: ball.x, y: ball.y});
                
                // 限制轨迹点数量
                if (ball.trailPoints.length > ball.trailMaxLength) {
                    ball.trailPoints.shift();
                }
                
                // 检查是否到达中间位置
                if (ball.x >= canvas.width / 2 && !ball.square.show) {
                    ball.square.show = true;
                }
            } else if (!ball.hasStopped) {
                ball.hasStopped = true;
                
                // 球体停止后，自动启动第一个抛出动画
                launchNewSquare();
            }
            
            // 当最后一个文本框开始移动时，抛出下一个小方块
            if (ball.hasStopped && ball.square.launchedSquares.length > 0) {
                const lastLaunched = ball.square.launchedSquares[ball.square.launchedSquares.length - 1];
                const progress = (Date.now() - lastLaunched.startTime) / lastLaunched.duration;
                
                // 当最后一个文本框开始移动时，抛出新的小方块
                if (progress > (lastLaunched.expandDuration + lastLaunched.staticDuration) / lastLaunched.duration * 0.7 && 
                    !lastLaunched.hasTriggeredNext) {
                    
                    launchNewSquare();
                    lastLaunched.hasTriggeredNext = true;
                }
            }
            
            // 更新速度线位置（无论球体是否停止都继续移动）
            ball.lines.forEach((line, index) => {
                line.x += line.speed;
                
                // 如果速度线超出画布右侧，重新放置到球体左侧
                if (line.x > canvas.width) {
                    ball.lines[index] = {
                        x: ball.x - ball.radius - Math.random() * 100,
                        y: ball.y + (Math.random() * 40 - 20),
                        length: ball.lineLength * (0.7 + Math.random() * 0.6),
                        speed: ball.speed * (1.5 + Math.random())
                    };
                }
            });
            
            // 更新旋转小方块
            if (ball.square.show) {
                ball.square.rotation += ball.square.rotationSpeed;
            }
            
            // 绘制所有元素
            drawTrail();
            drawLines();
            drawBall();
            
            // 继续动画循环
            requestAnimationFrame(update);
        }
        
        // 初始化并开始动画
        initLines();
        update();
    </script>
</body>
</html>
    